#
#   Hero.py
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; version 2 of the License.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   Copyright
#   Author: Nicholas F. Hoover
#   Contributors:
#   Created: 2007.07.22
#   Last Modified: 2007.11.07
#

import pygame
from Character import Character
from Animation import Animation
from PowerUp import PowerUp

class Hero(Character):
    """A playable character"""
    
    HERO_NAME = ''
    
    STATUS_TICKS_BETWEEN_UPDATES = 20
    STATUS_UPDATES_PER_SFX = 5
    REGEN_AMOUNT_PER_TICK = 1


    NUM_ANIMATIONS = 11
    (IDLE,
     WALK_UP,
     WALK_DOWN,
     WALK_SIDE,
     ATTACK1,
     ATTACK2,
     SPECIAL1,
     SPECIAL2,
     EAT,
     PICKUP,
     USE) = range(NUM_ANIMATIONS)

    LEFT = NUM_ANIMATIONS
    
    DEFAULT_ANIMATION = IDLE

    ACTIONS = [ATTACK1, ATTACK2, SPECIAL1, SPECIAL2, EAT, PICKUP, USE]
    
    MAX_POWERUPS_EAT = 3
    MAX_POWERUPS_PICKUP = 1
        
#####################
# INVENTORY BONUSES #
#####################
    FAST_SOUL_INTERCEPT = 0
    FAST_SOUL_SLOPE = 10
    FAST_SOUL_MAX = 6
    
    
    STRONG_SOUL_INTERCEPT = 5
    STRONG_SOUL_SLOPE = 20
    STRONG_SOUL_MAX = 5
    
    
    FAT_SOUL_INTERCEPT = 0
    FAT_SOUL_SLOPE = 10
    FAT_SOUL_MAX = 5

#############
# FUNCTIONS #
#############
    def __init__(self):
        Character.__init__(self)
        self.statusFunctions = []
        self.reset()
        

    def reset(self):
        Character.reset(self)
        
        self.speed_bonus = 0
        self.toughness_bonus = 0
        self.regen_bonus = 0
        
        self.statusUpdateCount = 0 #hunger/regen
        self.sfxUpdateCount = 0
        self.effects = []

        self.nextAction = self.IDLE
        self.nextFacing = self.facing

        self.inventory = range(PowerUp.NUM_ANIMATIONS)
        for i in range(PowerUp.NUM_ANIMATIONS):
            self.inventory[i] = 0

        
###########
# Updates #
###########

    def doStatusUpdate(self):
        self.statusUpdateCount += 1
        if self.statusUpdateCount == self.STATUS_TICKS_BETWEEN_UPDATES:
            self.statusUpdateCount = 0
            self.doRegen()
            for function in self.statusFunctions:
                if callable(function):
                    function()
            self.doEffects()
            self.doInventoryBonuses()
        elif self.statusUpdateCount == self.STATUS_TICKS_BETWEEN_UPDATES/2:
            self.sfxUpdateCount += 1
            if self.sfxUpdateCount == self.STATUS_UPDATES_PER_SFX:
                self.playSound(self.HERO_NAME + '_Misc')

 
#########
# STATS #
#########               
    def doRegen(self):
        self.incHealth(self.REGEN_AMOUNT_PER_TICK + self.regen_bonus)
 
    def decHealth(self, amount):
        if amount > self.toughness_bonus:
            amount -= self.toughness_bonus #do toughness
            prevHealth = self.health
            Character.decHealth(self, amount)
            if prevHealth > 20 and self.health <= 20:
                self.playSound(self.HERO_NAME + '_LowHealth')

    def doInventoryBonuses(self):
        #speed
        if self.inventory[PowerUp.DEAD_FASTKID] > self.FAST_SOUL_INTERCEPT:
            self.speed_bonus = (self.inventory[PowerUp.DEAD_FASTKID] - self.FAST_SOUL_INTERCEPT) / self.FAST_SOUL_SLOPE
            if self.speed_bonus > self.FAST_SOUL_MAX: self.speed_bonus = self.FAST_SOUL_MAX
        else:
            self.speed_bonus = 0
        #toughness
        if self.inventory[PowerUp.DEAD_STRONGKID] > self.STRONG_SOUL_INTERCEPT:
            self.toughness_bonus = (self.inventory[PowerUp.DEAD_STRONGKID] - self.STRONG_SOUL_INTERCEPT) / self.STRONG_SOUL_SLOPE
            if self.toughness_bonus > self.STRONG_SOUL_MAX: self.toughness_bonus = self.STRONG_SOUL_MAX
        else:
            self.toughness_bonus = 0
        #regen
        if self.inventory[PowerUp.DEAD_FATKID] > self.FAT_SOUL_INTERCEPT:
            self.regen_bonus = (self.inventory[PowerUp.DEAD_FATKID] - self.FAT_SOUL_INTERCEPT) / self.FAT_SOUL_SLOPE
            if self.regen_bonus > self.FAT_SOUL_MAX: self.regen_bonus = self.FAT_SOUL_MAX
        else:
            self.regen_bonus = 0
        

#############
# INVENTORY #
#############
    def _useItem(self, item):
        #decrement count
        self.inventory[item] -= 1
        #apply effect
        powerup = PowerUp(0, item)
        for effect in powerup.effects:
            self.addEffect(effect)        
            
    def addItem(self, item):
        #increment count
        self.inventory[item] += 1

    def viewItemCount(self, item):
        return self.inventory[item]
    
    def useItem(self, item):
        if self.canAct() and self.inventory[item] > 0:
            self.setAnimation(self.USE)
            self._useItem(item)
            if item == PowerUp.DRUGS:
                self.playSound(self.HERO_NAME + '_Drugs')
            else:
                self.playSound(self.HERO_NAME + '_Eat')

###########
# ACTIONS #
###########
    def attack1(self):
        if self.canAct():
            self.setAnimation(self.ATTACK1)
            self.playSound(self.HERO_NAME + '_Punch')

    def attack2(self):
        if self.canAct():
            self.setAnimation(self.ATTACK2)
            self.playSound(self.HERO_NAME + '_Kick')
    
    def eat(self):
        if self.canAct():
            self.setAnimation(self.EAT)
    
    def pickup(self):
        if self.canAct():
            self.setAnimation(self.PICKUP)

    def specialAttack1(self):
        pass

    def specialAttack2(self):
        pass

    def createAttack1Sprite(self):
        return 0

    def createAttack2Sprite(self):
        return 0

    def createSpecialAttack1Sprite(self):
        return 0

    def createSpecialAttack2Sprite(self):
        return 0
